﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using HslCommunication;
using HslCommunication.ModBus;
using System.Threading;
using System.Collections;
using HslCommunication.Controls;
using VzClientSDKDemo;
using System.Runtime.InteropServices;
using System.IO;
using System.Net;
using parkMonitor.entity;
using System.Diagnostics;
using System.Threading.Tasks;
using parkMonitor.model;
using parkMonitor.viewModel.objectTree;
using parkMonitor.server.uiLogServer;
using System.Configuration;
using parkMonitor.LOG;

namespace parkMonitor.server
{
    /// <summary>
    /// 号牌机通信类
    /// </summary>
    public partial class NumMachineLinker : Form, IEquipments
    {
        /// <summary>
        /// 刷新时间间隔与个数
        /// </summary>
        public const int REFRESHINGTIME = 500, FILTERINGNUMBER = 8;

        ///<summary>通过设备句柄访问pic；链接时add，系统关闭时remove</summary>
        private Dictionary<int, PictureBox> devPicMap = new Dictionary<int, PictureBox>();
        ///<summary>通过名字获取pic对象；创建pic时add,系统关闭remove</summary>
        private Dictionary<string, PictureBox> namePicMap = new Dictionary<string, PictureBox>();
        ///<summary>通过ip获取设备id；产生ip时创建</summary>
        private Dictionary<string, int> ipIdMap = new Dictionary<string, int>();
        ///<summary>通过ip获取设备句柄；产生句柄时创建</summary>
        private Dictionary<string, int> ipHandleMap = new Dictionary<string, int>();
        /// <summary>句柄到号牌回调映射</summary>
        private Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK> handleCallbackMap = new Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK>();
        ///<summary>号牌队列</summary>
        private Queue<NumberMachineNode> LicBuffer = new Queue<NumberMachineNode>();
        ///<summary>计数Map</summary>
        private Dictionary<string, Dictionary<NumberMachineNode, int>> filterMap = new Dictionary<string, Dictionary<NumberMachineNode, int>>();
        /// <summary>筛选计数</summary>
        private int filterCount = 0;
        /// <summary>系统关闭</summary>
        private bool isClosing = false;
        /// <summary>开启拍照的设备</summary>
        private int snapshotDevHandle = -1;
        /// <summary>允许无号牌时拍照</summary>
        private bool enableEmptySnapshot = true;

        private NumberMachineMessage nmMsg = new NumberMachineMessage();
        VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX find_DeviceCB = null;
        VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK m_PlateResultCB = null;
        private const int MSG_PLATE_INFO = 0x901;
        private const int MSG_DEVICE_INFO = 0x902;
        /// <summary>
        /// 用于消息传递机制
        /// </summary>
        public IntPtr hwndMain;

        /// <summary>
        /// 号牌机类构造函数
        /// </summary>
        public NumMachineLinker()
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();

            Thread thread = new Thread(new ThreadStart(DateTimeInfo));
            thread.IsBackground = true;
            thread.Start(); //显示当前时间            

            VzClientSDK.VzLPRClient_Setup();

            hwndMain = this.Handle;
            //m_sAppPath = System.IO.Directory.GetCurrentDirectory();
        }
        /// <summary>
        /// 定义时钟委托
        /// </summary>
        public delegate void SetDateTime();
        /// <summary>
        /// 实时采集
        /// </summary>
        public delegate void Begin_Read();

        private void FormSiemens_Load(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(DateTimeInfo));
            thread.IsBackground = true;
            thread.Start(); //显示当前时间            

            VzClientSDK.VzLPRClient_Setup();

            hwndMain = this.Handle;
            //m_sAppPath = System.IO.Directory.GetCurrentDirectory();
            //this.ShowInTaskbar = false;
            //this.Opacity = 0;

        }

        private void FormSiemens_FormClosing(object sender, FormClosingEventArgs e)
        {
            Stop();
        }

        private void DateTimeInfo()
        {
            try
            {
                while (!isClosing)
                {
                    SetDateTime setDate = new SetDateTime(
                    delegate
                    {
                        toolStripStatusLabel2.Text = DateTime.Now.ToString();
                    });
                    setDate();
                    Thread.Sleep(1000);
                }
                // ReSharper disable once FunctionNeverReturns
            }
            catch (Exception e) { Debug.Print(e.StackTrace); }

        }

        //******************************************************************************************************************

        private void UpdateStatus(NumberMachineNode nmn)
        {
            while (!isClosing)
            {
                if (GetStatus(nmn.ip) == 1)
                {
                    nmn.status = EnumNumberMachineStatus.Normal;
                }
                else
                {
                    //号牌机断线写日志
                    nmn.status = EnumNumberMachineStatus.Offline;
                    LogFile logError = LogFile.ERROR;
                    Log.WriteLog(logError, "正在与ip为 " + nmn.ip + " 的号牌机 进行连接。");
                    UILogServer.ins.info("正在与ip为 " + nmn.ip + " 的号牌机 进行连接。");
                    Thread.Sleep(10000);
                }
                Thread.Sleep(REFRESHINGTIME);
            }
        }

        private void Run()
        {
            try
            {
                while (!isClosing)
                {
                    Thread.Sleep(REFRESHINGTIME);
                    //定时返回号牌
                    lock (devPicMap)
                    {
                        Dictionary<int, PictureBox>.Enumerator devEnumer = devPicMap.GetEnumerator();
                        do
                        {
                            ActivateSnap(devEnumer.Current.Key);
                            //Debug.WriteLine(lv.data.Count.ToString()+":\n"+ lv.data[lv.data.Count-1].LicenseNum+ lv.data[lv.data.Count - 1].TimeRecord);
                        } while (devEnumer.MoveNext());
                    }
                    //读取设备ip与id映射关系
                    lock (ipHandleMap)
                    {
                        Dictionary<string, int>.Enumerator ipEnumer = ipHandleMap.GetEnumerator();
                        do
                        {
                            //映射关系不存在则读取配置文件
                            lock (ipIdMap)
                            {
                                if (ipEnumer.Current.Key != null && !ipIdMap.ContainsKey(ipEnumer.Current.Key))
                                {
                                    try
                                    {
                                        int id = Int32.Parse(ConfigurationManager.AppSettings.Get(ipEnumer.Current.Key));
                                        ipIdMap.Add(ipEnumer.Current.Key, id);
                                    }
                                    catch (Exception) { UILogServer.ins.log("读取号牌机编号映射失败，配置文件填写有误"); }
                                }
                            }
                        } while (ipEnumer.MoveNext());
                    }
                    lock (LicBuffer)
                    {
                        //删除已停好车的号牌
                        for (int i = 0; i < LicBuffer.Count; i++)
                        {
                            NumberMachineNode n = (NumberMachineNode)LicBuffer.Dequeue().Clone();
                            if (n.ip != "")
                            {
                                LicBuffer.Enqueue((NumberMachineNode)n.Clone());
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }

        ///<summary>寻找设备回调函数</summary>
        private void FIND_DEVICE_CALLBACK_EX(string pStrDevName, string pStrIPAddr, ushort usPort1, ushort usPort2, uint SL, uint SH, string netmask, string gateway, IntPtr pUserData)
        {
            string pStrDev = pStrIPAddr.ToString() + ":" + usPort1.ToString();
            string serialNO = SL.ToString() + ":" + SH.ToString() + ":" + netmask + ":" + gateway;

            VzClientSDK.VZ_LPR_DEVICE_INFO device_info = new VzClientSDK.VZ_LPR_DEVICE_INFO();
            device_info.device_ip = pStrDev;
            device_info.serial_no = serialNO;

            int size = Marshal.SizeOf(device_info);
            IntPtr intptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(device_info, intptr, true);

            //发送message，输出设备信息
            Win32API.PostMessage(hwndMain, MSG_DEVICE_INFO, (int)intptr, 0);
        }

        ///<summary>停止播放与设备句柄关联的视频</summary>
        private void StopPlay(int handleInput)
        {
            if (handleInput != 0)
            {
                int ret = VzClientSDK.VzLPRClient_StopRealPlay(handleInput);
            }
        }

        ///<summary>强制获取号牌</summary>
        private void ActivateSnap(int handle)
        {
            if (handle > 0)
            {
                VzClientSDK.VzLPRClient_ForceTrigger(handle);
            }

        }

        ///<summary>信息自动处理</summary>
        protected override void DefWndProc(ref Message m)
        {
            IntPtr intptr;
            VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInfo;
            VzClientSDK.VZ_LPR_DEVICE_INFO deviceInfo;

            int handle = 0;

            switch (m.Msg)
            {
                case MSG_PLATE_INFO:

                    intptr = (IntPtr)m.WParam.ToInt32();
                    handle = m.LParam.ToInt32();
                    if (intptr != null)
                    {
                        //根据句柄获取设备IP
                        string strIP = Get_IP(handle);
                        plateInfo = (VzClientSDK.VZ_LPR_MSG_PLATE_INFO)Marshal.PtrToStructure(intptr, typeof(VzClientSDK.VZ_LPR_MSG_PLATE_INFO));
                        SetDetail(plateInfo, strIP);

                        Marshal.FreeHGlobal(intptr);
                    }

                    break;

                case MSG_DEVICE_INFO:
                    intptr = (IntPtr)m.WParam.ToInt32();
                    if (intptr != null)
                    {
                        deviceInfo = (VzClientSDK.VZ_LPR_DEVICE_INFO)Marshal.PtrToStructure(intptr, typeof(VzClientSDK.VZ_LPR_DEVICE_INFO));
                        DeviceLink(deviceInfo.device_ip, deviceInfo.serial_no);
                        Marshal.FreeHGlobal(intptr);

                    }
                    break;

                default:
                    base.DefWndProc(ref m);
                    break;
            }
        }

        ///<summary>ip+port字符串转ipe</summary>
        private void GetIpEndPoint(string ipp, out IPEndPoint ipe)
        {
            IPAddress myIP = IPAddress.Parse(ipp.Remove(ipp.LastIndexOf(':')) + "");
            string myPort = ipp.Substring(ipp.IndexOf(':') + 1);
            ipe = new IPEndPoint(myIP, int.Parse(myPort));
        }

        ///<summary>与设备连接，启动更新设备状态线程，输出视频</summary>
        private void DeviceLink(string pStrDev, string serialNO)
        {
            IPEndPoint ipe;
            GetIpEndPoint(pStrDev, out ipe);
            string ip = ipe.Address.ToString();
            if (ipHandleMap.ContainsKey(ip))
            {
                //MessageBox.Show("设备已分配句柄");
                return;
            }
            int handle = 0;
            //找到设备，加入list
            NumberMachineNode node = new NumberMachineNode(ip, 0, "", "", 1);
            nmMsg.data.Add(node);
            handle = VzClientSDK.VzLPRClient_Open(ip, (ushort)80, "admin", "admin");
            Task.Factory.StartNew(() =>
            {
                UpdateStatus(node);
            });
            if (handle == 0)
            {
                return;
            }

            VzClientSDK.VzLPRClient_SetVideoEncodeType(handle, 0);
            //将句柄加入
            lock (ipHandleMap)
            {
                ipHandleMap.Add(ip, handle);
            }
            //MessageBox.Show("摄像头打开成功");
            lock (handleCallbackMap)
            {
                handleCallbackMap.Add(handle, null);
            }
            //链接句柄到新PictureBox
            VideoOutput(handle);
        }

        ///<summary>视频输出</summary>
        private void VideoOutput(int handle)
        {
            try
            {
                lock (devPicMap)
                {
                    lock (handleCallbackMap)
                    {
                        //存在设备则复位并在原pic上输出
                        if (devPicMap.ContainsKey(handle))
                        {
                            VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
                            PictureBox pic;
                            if (devPicMap.TryGetValue(handle, out pic) && handleCallbackMap.ContainsKey(handle))
                            {
                                int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic.Handle);
                                // 设置车牌识别结果回调
                                handleCallbackMap[handle] = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
                                VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, handleCallbackMap[handle], IntPtr.Zero, 1);
                                //m_PlateResultCB = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
                                //VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, m_PlateResultCB, IntPtr.Zero, 1);
                                //VzClientSDK.VzLPRClient_StopRealPlay(handle);
                            }
                        }
                        else//否则找一个空位加pic
                        {
                            for (int i = 0; i < 20; i++)
                            {
                                string str = "PictureBox" + Convert.ToString(i);
                                //该名称对应控件不存在,则创建并链接pic
                                lock (namePicMap)
                                {
                                    if (!namePicMap.ContainsKey(str) && handleCallbackMap.ContainsKey(handle))
                                    {
                                        PictureBox pic;
                                        if (CreatePic(i, out pic))
                                        {
                                            devPicMap.Add(handle, pic);
                                            //ipIdMap.Add(Get_IP(handle), i);
                                            VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
                                            int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic.Handle);
                                            // 设置车牌识别结果回调
                                            handleCallbackMap[handle] = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
                                            VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, handleCallbackMap[handle], IntPtr.Zero, 1);
                                            //m_PlateResultCB = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
                                            //VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, m_PlateResultCB, IntPtr.Zero, 1);
                                            //VzClientSDK.VzLPRClient_StopRealPlay(handle);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                Debug.WriteLine("jumped out");
            }
        }

        ///<summary>号牌信息回调</summary>
        private int OnPlateResult(int handle, IntPtr pUserData,
                                                IntPtr pResult, uint uNumPlates,
                                                VzClientSDK.VZ_LPRC_RESULT_TYPE eResultType,
                                                IntPtr pImgFull,
                                                IntPtr pImgPlateClip)
        {
            if (eResultType != VzClientSDK.VZ_LPRC_RESULT_TYPE.VZ_LPRC_RESULT_REALTIME)
            {
                VzClientSDK.TH_PlateResult result = (VzClientSDK.TH_PlateResult)Marshal.PtrToStructure(pResult, typeof(VzClientSDK.TH_PlateResult));
                string strLicense = new string(result.license);

                VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInfo = new VzClientSDK.VZ_LPR_MSG_PLATE_INFO();
                plateInfo.plate = strLicense;

                //根据setMessage中通过id信息找到的handle保存图片
                if (handle == snapshotDevHandle)
                {
                    if (enableEmptySnapshot || !strLicense.Contains("_无_"))
                    {
                        string strFilePath = ConfigurationManager.AppSettings["LogPath"] + DateTime.Now.ToString("yyyyMMdd") + "\\";
                        if (!Directory.Exists(strFilePath))
                        {
                            Directory.CreateDirectory(strFilePath);
                        }
                        string ip = Get_IP(handle);
                        string path = strFilePath + ip + "-" + DateTime.Now.ToString("hh_mm_ss") + ".jpg";
                        int temp = VzClientSDK.VzLPRClient_ImageSaveToJpeg(pImgFull, path, 50);
                        if (temp != -1)
                        {
                            LogFile logFile = LogFile.LOG;
                            Log.WriteLog(logFile, "号牌机" + ip + "已拍照，图片保存于 " + strFilePath);
                            UILogServer.ins.info("号牌机" + ip + "已拍照，图片保存于 " + strFilePath);
                        }
                        else
                        {
                            UILogServer.ins.info("图片保存失败");
                        }
                    }
                    snapshotDevHandle = -1;
                }
                int size = Marshal.SizeOf(plateInfo);
                IntPtr intptr = Marshal.AllocHGlobal(size);
                Marshal.StructureToPtr(plateInfo, intptr, true);

                //发送消息，号牌信息
                Win32API.PostMessage(hwndMain, MSG_PLATE_INFO, (int)intptr, handle);
            }

            return 0;
        }


        ///<summary>记录车牌，时间，状态信息；刷新本地entity，并且入buffer</summary>
        private void SetDetail(VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInformation, string strIP)
        {
            int stat = GetStatus(strIP);
            bool found = false;
            int id = 0;
            lock (ipIdMap)
            {
                if (!ipIdMap.ContainsKey(strIP))
                {
                    try
                    {
                        id = Int32.Parse(ConfigurationManager.AppSettings.Get(strIP));
                        ipIdMap.Add(strIP, id);
                    }
                    catch (Exception) { UILogServer.ins.error("读取号牌机编号映射失败，配置文件填写有误"); }
                }
            }
            //检查设备是否存在
            foreach (NumberMachineNode nmn in nmMsg.data)
            {
                //相同设备
                if (nmn.ip == strIP)
                {
                    found = true;
                    //号牌不为空
                    if (!(plateInformation.plate == "_无_"))
                    {
                        nmn.SetLic(strIP, nmn.id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
                        FilterLic(strIP, (NumberMachineNode)nmn.Clone());
                    }
                    //号牌为空
                    else
                    {
                        nmn.SetLic(strIP, nmn.id, "", "", GetStatus(strIP));
                    }
                }
            }
            //新设备
            if (!found)
            {
                lock (ipIdMap)
                {
                    if (!(plateInformation.plate == "_无_") && ipIdMap.TryGetValue(strIP, out id))
                    {
                        NumberMachineNode nmn = new NumberMachineNode(strIP, id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
                        NumberMachineNode nmnc = (NumberMachineNode)nmn.Clone();
                        nmMsg.data.Add(nmnc);
                        FilterLic(strIP, nmnc);
                    }
                    else
                    {
                        nmMsg.data.Add(new NumberMachineNode(strIP, id, "", "", GetStatus(strIP)));
                    }
                }
            }
        }

        ///<summary>筛选号牌</summary>
        private void FilterLic(string ip, NumberMachineNode nmn)
        {
            Dictionary<NumberMachineNode, int> filter;
            //该filter不存在则创建
            if (!filterMap.ContainsKey(ip))
            {
                filter = new Dictionary<NumberMachineNode, int>();
                filterMap.Add(ip, filter);
            }
            //计数器异常
            else if (!filterMap.TryGetValue(ip, out filter))
            {
                return;
            }

            //filter计数
            int count = 0;
            if (filter.ContainsKey(nmn) && filter.TryGetValue(nmn, out count))//存在则数量+1
            {
                filter.Remove(nmn);
                filter.Add(nmn, count + 1);
            }
            else//不存在则计数1
            {
                filter.Add(nmn, 1);
            }

            filterCount += 1;
            //达到计数限制，计算众数是否达标，达标则入队
            if (filterCount >= FILTERINGNUMBER)
            {
                lock (LicBuffer)
                {
                    Dictionary<NumberMachineNode, int>.Enumerator enumer = filter.GetEnumerator();
                    do
                    {
                        //遍历，筛到号牌则入队
                        if (enumer.Current.Value >= (int)(filterCount * 0.5) && enumer.Current.Key != null && !LicBuffer.Contains(enumer.Current.Key))
                        {
                            if (nmMsg.aNode == null || nmMsg.aNode.LicenseNum == null || nmMsg.aNode.LicenseNum != enumer.Current.Key.LicenseNum)
                            {
                                NumberMachineNode node = (NumberMachineNode)enumer.Current.Key.Clone();
                                if (ipIdMap.TryGetValue(node.ip, out node.id))
                                {
                                    LicBuffer.Enqueue((NumberMachineNode)node.Clone());
                                }
                            }
                        }
                    } while (enumer.MoveNext());
                    filterCount = 0;
                    filter.Clear();
                }
            }
        }

        ///<summary>创建新pic并记录在picNameMap</summary>
        private bool CreatePic(int index, out PictureBox pb)
        {
            pb = new PictureBox
            {
                Width = 230,
                Height = 180,
                AutoSize = false,
                Name = "PictureBox" + Convert.ToString(index)
            };
            lock (namePicMap)
            {
                if (!namePicMap.ContainsKey(pb.Name))
                {
                    flowLayoutPanel1.Controls.Add(pb);
                    namePicMap.Add(pb.Name, pb);
                    return true;
                }
                else
                    return false;
            }
        }

        ///<summary>更新设备状态</summary>
        private int GetStatus(string devIP)
        {
            int myHandle;
            byte stat = 0;
            if (ipHandleMap.TryGetValue(devIP, out myHandle))
            {
                VzClientSDK.VzLPRClient_IsConnected(myHandle, ref stat);
                return stat;
            }
            return -1;
        }

        private string Get_IP(int lprHandle)
        {
            byte[] strDecIP = new byte[32];
            int max_count = 32;
            int ret = VzClientSDK.VzLPRClient_GetDeviceIP(lprHandle, ref strDecIP[0], max_count);
            string strIP = System.Text.Encoding.Default.GetString(strDecIP);
            strIP = strIP.TrimEnd('\0');
            return strIP;
        }

        private void flowLayoutPanel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private bool NodeValidation(NumberMachineNode node)
        {
            return (node != null && node.ip != null && node.ip != "" && node.ip != "used" && node.LicenseNum != null && node.LicenseNum != "") ? true : false;
        }

        /// <summary>
        /// 系统启动
        /// </summary>
        public void Start()
        {
            Task.Run(() =>
            {
                isClosing = false;

                try
                {
                    VzClientSDK.VZLPRClient_StopFindDevice();

                    find_DeviceCB = new VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX(FIND_DEVICE_CALLBACK_EX);
                    int ret = VzClientSDK.VZLPRClient_StartFindDeviceEx(find_DeviceCB, IntPtr.Zero);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                }
                //this.Show();
            });

            Task.Factory.StartNew(() =>
            {
                Run();
            });

            //Task imgTest = Task.Factory.StartNew(() =>
            //{
            //    while (!isClosing)
            //    {
            //        Command cmd = new Command
            //        {
            //            id = 1
            //        };
            //        SetMessage(cmd);
            //        Thread.Sleep(3000000);
            //    }
            //});

        }

        /// <summary>
        /// 系统关闭
        /// </summary>
        public void Stop()
        {
            VzClientSDK.VZLPRClient_StopFindDevice();
            lock (devPicMap)
            {
                Dictionary<int, PictureBox>.Enumerator enumer = devPicMap.GetEnumerator();
                do
                {
                    if (enumer.Current.Key != 0)
                    {
                        StopPlay(enumer.Current.Key);
                        VzClientSDK.VzLPRClient_Close(enumer.Current.Key);
                        flowLayoutPanel1.Controls.Remove(enumer.Current.Value);
                    }
                } while (enumer.MoveNext());
                isClosing = true;
                devPicMap.Clear();
            }
            lock (namePicMap) { namePicMap.Clear();}
            lock (ipIdMap) { ipIdMap.Clear();}
            lock (ipHandleMap) { ipHandleMap.Clear();}
            //this.Close();
        }

        /// <summary>
        /// 监控线程获取号牌机信息，核心线程获取号牌信息
        /// </summary>
        public AbstractMessage GetMessage()
        {
            lock (LicBuffer)
            {
                //准备输出的数据中存在非法Node，且LicBuffer可出队产生一个合法Node，则替换该非法Node，否则让Node=null
                if (!NodeValidation(nmMsg.aNode))
                {
                    for (int i = 0; i < LicBuffer.Count; i++)
                    {
                        NumberMachineNode n = LicBuffer.Dequeue();
                        if (NodeValidation(n))
                        {
                            if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
                            {
                                LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
                            }
                            nmMsg.aNode = n;
                            break;
                        }
                        else
                        {
                            LicBuffer.Enqueue(n);
                        }
                    }
                }
            }
            //if (NodeValidation(nmMsg.aNode) && ipIdMap.TryGetValue(nmMsg.aNode.ip, out int id))
            //{
            //    nmMsg.aNode.id = id;
            //}
            return nmMsg;
        }

        /// <summary>
        /// 一次停车流程完成时调用该方法，发送已完成车辆号牌信息
        /// </summary>
        /// <param name="message">已完成车辆的号牌相关信息存于message的aNode中,用于标记需清空的号牌</param>
        public void SetMessage(AbstractMessage message)
        {
            if (message.GetType().Equals(typeof(NumberMachineMessage)))
            {
                NumberMachineNode n = ((NumberMachineMessage)message).aNode;
                lock (LicBuffer)
                {
                    //输入号牌格式无误
                    if (n != null && n.ip != null && n.ip == "")
                    {
                        //与类成员变量中aNode号牌相同，将其ip复位表示已使用，重新入队等待清除
                        if (nmMsg != null && nmMsg.aNode != null && nmMsg.aNode.LicenseNum.Equals(n.LicenseNum))
                        {
                            nmMsg.aNode.ip = "";
                            LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
                            nmMsg.aNode = null;
                        }
                        //搜索号牌队列，将相应号牌置空，准备清除
                        else
                        {
                            for (int i = 0; i < LicBuffer.Count; i++)
                            {
                                NumberMachineNode temp = LicBuffer.Dequeue();
                                //已匹配上，ip置空
                                if (temp.LicenseNum.Equals(n.LicenseNum))
                                {
                                    temp.ip = "";
                                    LicBuffer.Enqueue(temp);
                                    break;
                                }
                                LicBuffer.Enqueue(temp);
                            }
                        }
                    }
                }
            }
            //传入异常号牌，根据ip找到handle，改变snapshotDevHandle的值在回调函数中截图
            if (message.GetType().Equals(typeof(Command)))
            {
                Command cmd = (Command)message;
                if (cmd != null && cmd.id != 0)
                {
                    lock (ipIdMap)
                    {
                        Dictionary<string, int>.Enumerator enumerator = ipIdMap.GetEnumerator();
                        do
                        {
                            // if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out int handle))
                            int handle = 0;
                            if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out handle))
                            {
                                snapshotDevHandle = handle;
                                break;
                            }
                        } while (enumerator.MoveNext());
                    }
                }
                else
                {
                    UILogServer.ins.error("参数错误，图片未保存");
                }
            }

        }
    }
    /// <summary>
    /// 消息发送api
    /// </summary>
    public class Win32API
    {
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);

        /// <summary>
        /// 自定义的结构
        /// </summary>
        public struct My_lParam
        {
            public int i;
            public string s;
        }
        /// <summary>
        /// 使用COPYDATASTRUCT来传递字符串
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }
        //消息发送API
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
           int Msg,            // 消息ID
            int wParam,         // 参数1
            int lParam          //参数2
        );


        //消息发送API
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
           int Msg,            // 消息ID
            int wParam,         // 参数1
            ref My_lParam lParam //参数2
        );

        //消息发送API
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
           int Msg,            // 消息ID
            int wParam,         // 参数1
            ref COPYDATASTRUCT lParam  //参数2
        );

        //消息发送API
        [DllImport("User32.dll", EntryPoint = "PostMessage")]
        public static extern int PostMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
           int Msg,            // 消息ID
            int wParam,         // 参数1
            int lParam            // 参数2
        );


        //消息发送API
        [DllImport("User32.dll", EntryPoint = "PostMessage")]
        public static extern int PostMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
           int Msg,            // 消息ID
            int wParam,         // 参数1
            ref My_lParam lParam //参数2
        );

        //异步消息发送API
        [DllImport("User32.dll", EntryPoint = "PostMessage")]
        public static extern int PostMessage(
            IntPtr hWnd,        // 信息发往的窗口的句柄
           int Msg,            // 消息ID
            int wParam,         // 参数1
            ref COPYDATASTRUCT lParam  // 参数2
        );

    }
}
